﻿#region using statements
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;
using System.Data;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Text;

using Microsoft.SharePoint;
using Microsoft.SharePoint.WebControls;

using Microsoft.Office.Word.Server.Service;
using Microsoft.Office.Word.Server.Conversions;
#endregion

namespace WordServicesUIExtensions
{
    #region data classess
    [Serializable]
    public class WordServicesConversionJob
    {
        Guid _jobId;
        public Guid JobId {
            get
            {
                return _jobId;
            }
            set
            {
                _jobId = value;
            }
        }
        
        String _jobName;
        public String JobName {
            get
            {
                return _jobName;
            }
            set
            {
                _jobName = value;
            }
        }

        DateTime _submittedTime;
        public DateTime SubmittedTime
        {
            get
            {
                return _submittedTime;
            }
            set
            {
                _submittedTime = value;
            }
        }
        
        string _saveFormat;
        public String SaveFormat
        {
            get
            {
                return _saveFormat;
            }
            set
            {
                _saveFormat = value;
            }
        }

        JobStatus _status;
        public JobStatus Status
        {
            get
            {
                return _status;
            }
            set
            {
                _status = value;
            }
        }

        string _statusMessage;
        public String StatusMessage
        {
            get
            {
                return _statusMessage;
            }
            set
            {
                _statusMessage = value; 
            }
        }

        string _outputFile;
        public string OutputFile
        {
            get
            {
                return _outputFile;
            }
            set
            {
                _outputFile = value;
            }
        }

        #region constructors
        public WordServicesConversionJob(Guid jobId, string name, DateTime submittedTime)
        {
            this.JobId = jobId;
            this.JobName = name;
            this.SubmittedTime = submittedTime;
        }
        public WordServicesConversionJob() { }
        #endregion

    }
    
    public enum JobStatus
    {
        Running,
        Completed,
        Failed,
        Cancelled
    }

    internal class Constants
    {
        public const string SharePointImagesDirectory = "/_layouts/images";

    }
    #endregion

    #region item templates
    public class ConversionJobStatusTemplate : ITemplate
    {
        private ListItemType _itemType;

        public ConversionJobStatusTemplate(ListItemType itemType)
        {
            this._itemType = itemType;
        }

        public void InstantiateIn(Control container)
        {            
            switch (_itemType)
            {
                case ListItemType.Item:
                    Image statusIcon = new Image();
                    statusIcon.ID = "statusIcon";
                    statusIcon.ImageAlign = ImageAlign.AbsMiddle;
                    statusIcon.BorderWidth = 0; 
                    statusIcon.DataBinding += new EventHandler(StatusIcon_DataBinding);
                    container.Controls.Add(statusIcon);
                    break;
            }
        }

        void StatusIcon_DataBinding(object sender, EventArgs e)
        {
            Image statusIcon = (Image)sender;
            SPGridViewRow container = (SPGridViewRow)statusIcon.NamingContainer;
            if (container != null)
            {
                WordServicesConversionJob item = container.DataItem as WordServicesConversionJob;
                if (item != null)
                {
                    switch (item.Status)
                    {
                        case JobStatus.Running:
                            statusIcon.ImageUrl = string.Format(@"{0}/synchronizationtitle.png", Constants.SharePointImagesDirectory);
                            break;
                        case JobStatus.Cancelled:
                            statusIcon.ImageUrl = string.Format(@"{0}/ctor32.png", Constants.SharePointImagesDirectory);
                            break;
                        case JobStatus.Completed:
                            statusIcon.ImageUrl = string.Format(@"{0}/workflowstatus_completed.png", Constants.SharePointImagesDirectory);
                            break;
                        case JobStatus.Failed:
                            statusIcon.ImageUrl = string.Format(@"{0}/error32by32.gif", Constants.SharePointImagesDirectory);
                            break;
                    }
                }
            }
        }
    }
    
    public class ConversionJobStatusMessageTemplate : ITemplate
    {
        ListItemType _itemType;

        public ConversionJobStatusMessageTemplate(ListItemType itemType)
        {
            this._itemType = itemType;        
        }

        public void InstantiateIn(Control container)
        {
            switch (_itemType)
            {
                case ListItemType.Item:
                    TextBox tb = new TextBox();
                    tb.TextMode = TextBoxMode.MultiLine;
                    tb.Rows = 10;
                    tb.Columns = 50;
                    tb.ID = "jobStatusMessageTextBox";
                    tb.Enabled = false;
                    tb.Style.Add(HtmlTextWriterStyle.BorderWidth, "0");
                    tb.Style.Add(HtmlTextWriterStyle.BorderStyle, "none");
                    tb.DataBinding += new EventHandler(JobStatusMessage_DataBinding);
                    container.Controls.Add(tb);
                    break;
            }
        }

        void JobStatusMessage_DataBinding(object sender, EventArgs e)
        {
            TextBox tb = (TextBox)sender;
            SPGridViewRow container = tb.NamingContainer as SPGridViewRow;
            tb.Text = DataBinder.Eval(container.DataItem, "StatusMessage").ToString();
        }
    }

    #endregion

    public partial class ConversionStatus : LayoutsPageBase
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            SetUpGridView();
            if (!Page.IsPostBack)
            {
                List<WordServicesConversionJob> jobs = GetAllJobs();
                ConversionJobsGridView.DataSource = jobs;
                ConversionJobsGridView.DataBind();
            }
        }
        /// <summary>
        /// retrieves all word services conversion requests via OM including the job status
        /// </summary>
        /// <returns>All conversion jobs with status</returns>
        List<WordServicesConversionJob> GetAllJobs()
        {
            List<WordServicesConversionJob> ret = new List<WordServicesConversionJob>();
            WordServiceApplicationProxy proxy = (WordServiceApplicationProxy)SPServiceContext.Current.GetDefaultProxy(typeof(WordServiceApplicationProxy));
            ReadOnlyCollection<ConversionJobInfo> allJobs = ConversionJobStatus.GetAllJobs(proxy, null);
            
            foreach (ConversionJobInfo job in allJobs)
            {
                WordServicesConversionJob item = new WordServicesConversionJob(job.JobId, job.Name, job.SubmittedTime);
                ConversionJobStatus jobStatus = new ConversionJobStatus(proxy, job.JobId, null);

                if (jobStatus.Count == jobStatus.Succeeded)
                {
                    item.Status = JobStatus.Completed;
                    item.StatusMessage = GetSuccededItemsStatusMessage(jobStatus);
                }
                else if (jobStatus.Count == jobStatus.Canceled)
                {
                    item.Status = JobStatus.Cancelled;
                    item.StatusMessage = "Job was cancelled";
                }
                else if (jobStatus.Count == jobStatus.Failed)
                {
                    item.Status = JobStatus.Failed;
                    item.StatusMessage = GetFailedItemsStatusMessage(jobStatus);
                }
                else
                {
                    //job is currently in progress, show progress in status message field
                    item.Status = JobStatus.Running;
                    item.StatusMessage = "Completed Items \n" + GetSuccededItemsStatusMessage(jobStatus) + "\n Failed Items \n" + 
                        GetFailedItemsStatusMessage(jobStatus) ;
                }
                ret.Add(item);
            }
            return ret;
        }
        
        string GetSuccededItemsStatusMessage(ConversionJobStatus jobStatus)
        {
            StringBuilder statusMessage = new StringBuilder();
            ReadOnlyCollection<ConversionItemInfo> succededItems = jobStatus.GetItems(ItemTypes.Succeeded);
            foreach (ConversionItemInfo ci in succededItems)
            {
                statusMessage.Append(String.Format("Input file :{0} successfully converted to :{1} at {2}", ci.InputFile, ci.OutputFile, ci.CompleteTime));
            }
            return statusMessage.ToString();
        }

        string GetFailedItemsStatusMessage(ConversionJobStatus jobStatus)
        {
            StringBuilder statusMessage = new StringBuilder();
            ReadOnlyCollection<ConversionItemInfo> failedItems = jobStatus.GetItems(ItemTypes.Failed);
            foreach (ConversionItemInfo ci in failedItems)
            {
                statusMessage.Append(String.Format("Conversion of file :{0} to {1} failed at {2} with error message: {3}", ci.InputFile, ci.OutputFile, ci.CompleteTime, ci.ErrorMessage));
            }
            return statusMessage.ToString();
        }

        void SetUpGridView()
        {
            if (ConversionJobsGridView.Columns.Count == 0)
            {
                var boundField = new BoundField();
                boundField.DataField = "JobId";
                boundField.HeaderText = "JOB ID";
                ConversionJobsGridView.Columns.Add(boundField);

                //Name
                boundField = new BoundField();
                boundField.DataField = "JobName";
                boundField.HeaderText = "JOB NAME";
                ConversionJobsGridView.Columns.Add(boundField);

                //submitted time
                boundField = new BoundField();
                boundField.HeaderText = "TIME SUBMITTED";
                boundField.DataField = "SubmittedTime";
                ConversionJobsGridView.Columns.Add(boundField);

                //Save Format
                //boundField = new BoundField();
                //boundField.HeaderText = "Save Format" ;
                //boundField.DataField = "SaveFormat";
                //ConversionJobsGridView.Columns.Add(boundField);

                //Status
                TemplateField templateField = new TemplateField();
                templateField.HeaderText = "STATUS";
                templateField.ItemTemplate = new ConversionJobStatusTemplate(ListItemType.Item);
                ConversionJobsGridView.Columns.Add(templateField);

                //Status Message
                templateField = new TemplateField();
                templateField.HeaderText = "STATUS MESSAGE";
                templateField.ItemTemplate = new ConversionJobStatusMessageTemplate(ListItemType.Item);
                ConversionJobsGridView.Columns.Add(templateField);                
            }
        }
    }
}
